#!/usr/bin/perl
package main;
use strict;
use POSIX;
use Config::Simple;
use Data::Dumper;
use File::Pid;

my ($Config, %config);

BEGIN {
  # Set our name to 'chronicd' so users can send signals by name
  $0 = "chronicd";
  $SIG{KILL} = $SIG{INT} = $SIG{TERM} = $SIG{HUP} = $SIG{PIPE} = \&signal_handler;

  # get config
  my $config_filename = shift @ARGV || '/etc/chronic.conf';
  warn "using configuration file : $config_filename\n";

  die "couldn't find configuration file" unless (-f $config_filename);

  $Config = new Config::Simple($config_filename);
  %config = $Config->vars();
  # $user = $Config->param('User');
  die "couldn't read configuration" unless ($Config->param('hostname'));

  $ENV{CHRONIC_DSN} = $Config->param('dsn');

  warn "dsn : '$ENV{CHRONIC_DSN}' /", $Config->param('dsn');

  use Schedule::Chronic::Distributed;
}

# check for previous instance running
my $pidfile = File::Pid->new({ file => $config{pidfile} || '/var/run/chronicd.pid', });
if ( my $cur_pid = $pidfile->running ) {
  die "Already running: $cur_pid\n";
}

# become daemon
my $parent_pid = $$;
warn "parent : $parent_pid\n";
my $pid = fork;
exit if $pid;
die "Couldn't fork: $!" unless defined($pid);
POSIX::setsid() or die "Can't start a new session: $!";

# check for previously running instance and updated pidfile
$pidfile = File::Pid->new({ file => $config{pidfile} || '/var/run/chronicd.pid', });
if ( my $cur_pid = $pidfile->running ) {
  die "Already running: $cur_pid\n";
}
$pidfile->write;

warn "forked child : $$\n";

# set up scheduler
our $chronic = new Schedule::Chronic::Distributed ( debug => 0, logtype => 'syslog', config => {%config}, pidfile_handler => $pidfile );
warn "starting.. schedule\n";

# run schedule
$chronic->schedule();

# trap and handle signals
sub signal_handler {
  my $signal = shift;
  warn  "[".localtime()."] (pid $$) caught some signal '$signal' - exiting";
  warn "caller : ", join(', ',caller());
  exit;
}

END {
  warn "\n\nending..\n";
  exit if ($parent_pid == $$);
  warn "pid : $$, parent $parent_pid\n";

  my $chronic = $main::chronic;
  my $am_child = $chronic->am_a_child();
  warn "am_child : $am_child\n";
  if ($am_child) {
    warn "chronicd child worker ( $$ ) finishing..\n";
  } else {
      warn "chronicd [$$] [".localtime()."] ending";
      warn "updating node availability to 0";
      eval {$chronic->update_node_availability(0); };
      warn "couldn't update node availability for node : $@\n" if ($@);
      warn "stopping workers\n";
      $chronic->stop_workers();
      warn "removing pidfile\n";
      eval {$chronic->pidfile_handler->remove;};
      warn "couldn't removed pidfile : $@\n" if ($@);
  }
}
